home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / scsiDiskBoot / devSCSIDisk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-13  |  10.2 KB  |  374 lines

  1. /* 
  2.  * devScsiDisk.c --
  3.  *
  4.  *      SCSI Command formatter for SCSI type 0 (Direct Access Devices.) 
  5.  *    This file implements the BlockDevice interface to SCSI disk.
  6.  *
  7.  * Copyright 1986 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifdef notdef
  19. static char rcsid[] = "$Header: /sprite/src/kernel/dev/RCS/devSCSIDisk.c,v 8.6 89/05/23 09:59:42 mendel Exp Locker: brent $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include "sprite.h"
  24. #include "fs.h"
  25. #include "dev.h"
  26. #include "devInt.h"
  27. #include "scsi.h"
  28. #include "scsiDevice.h"
  29. #include "devDiskLabel.h"
  30. #include "devDiskStats.h"
  31. #include "devBlockDevice.h"
  32. #include "stdlib.h"
  33. #include "dev/scsi.h"
  34. #include "boot.h"
  35. #include "dbg.h"
  36.  
  37. typedef struct DiskMap {
  38.     int     firstSector;
  39.     int     sizeInSectors;
  40. } DiskMap;
  41.  
  42. /*
  43.  * State info for an SCSI Disk.  This gets allocated and filled in by
  44.  * the attach procedure. 
  45.  */
  46. typedef struct ScsiDisk {
  47.     DevBlockDeviceHandle blockHandle; /* Must be FIRST field. */
  48.     ScsiDevice    *devPtr;          /* SCSI Device we have open. */
  49.     int            partition;  /* What partition we want. A partition number
  50.                  * of -1 means the whole disk.
  51.                  */
  52.     int sizeInSectors;        /* The number of sectors on disk */
  53.     DiskMap map[DEV_NUM_DISK_PARTS];    /* The partition map */
  54.     int type;        /* Type of the drive, needed for error checking */
  55.     Sys_DiskStats *diskStatsPtr;    /* Area for disk stats. */    
  56. } ScsiDisk;
  57.  
  58. typedef struct ScsiDiskCmd {
  59.     ScsiDisk    *diskPtr;    /* Target disk of command. */
  60.     ScsiCmd    scsiCmd;    /* SCSI command to send to disk. */
  61. } ScsiDiskCmd;
  62.  
  63.  
  64. #define    SCSI_DISK_SECTOR_SIZE    DEV_BYTES_PER_SECTOR
  65.  
  66. #define    RequestDone(requestPtr,status,byteCount) \
  67.     ((requestPtr)->doneProc)((requestPtr),(status),(byteCount))
  68.  
  69. static ReturnStatus DiskError();
  70. static Boolean    ScsiDiskIdleCheck();
  71.  
  72.  
  73. /*
  74.  *----------------------------------------------------------------------
  75.  *
  76.  * InitDisk --
  77.  *
  78.  *    Initialize the device driver state for a SCSI Disk. 
  79.  *
  80.  * Results:
  81.  *    The ScsiDisk structure. NIL - if there is an error attaching the
  82.  *    disk.
  83.  *
  84.  * Side effects:
  85.  *    The disk's label is read and saved in a ScsiDisk structure.  This
  86.  *    is allocated here.
  87.  *
  88.  *----------------------------------------------------------------------
  89.  */
  90. static ScsiDisk *
  91. InitDisk(devPtr,readLabel)
  92.     ScsiDevice    *devPtr; /* SCSI Handle for device. */
  93.     Boolean    readLabel;   /* TRUE if we should read and fill in label 
  94.                   * fields. */
  95. {
  96.     ScsiDisk    *diskPtr;
  97.     ReturnStatus status;
  98.     diskPtr = (ScsiDisk *) malloc(sizeof(ScsiDisk));
  99.     diskPtr->devPtr = devPtr;
  100.  
  101.     return(diskPtr);
  102. }
  103.  
  104. /*
  105.  *----------------------------------------------------------------------
  106.  *
  107.  * DiskDoneProc --
  108.  *
  109.  *    Call back routine for request to SCSI Disk. 
  110.  *
  111.  * Results:
  112.  *    None.
  113.  *
  114.  * Side effects:
  115.  *    Request call may be woken up.
  116.  *
  117.  *----------------------------------------------------------------------
  118.  */
  119.  
  120. static int
  121. DiskDoneProc(scsiCmdPtr, status, statusByte, byteCount, senseLength, 
  122.          senseDataPtr)
  123.     ScsiCmd    *scsiCmdPtr;    /* Request that finished. */
  124.     ReturnStatus  status;    /* Error of request. */
  125.     unsigned char statusByte;    /* SCSI status byte of request. */
  126.     int        byteCount;    /* Number of bytes transferred. */
  127.     int        senseLength;    /* Length of sense data returned. */
  128.     Address    senseDataPtr;    /* Sense data. */
  129. {
  130.     DevBlockDeviceRequest *requestPtr;
  131.     ScsiDisk    *diskPtr;
  132.  
  133.     requestPtr = (DevBlockDeviceRequest *) (scsiCmdPtr->clientData);
  134.     diskPtr = ((ScsiDiskCmd *) (requestPtr->ctrlData))->diskPtr;
  135.     status = DiskError(diskPtr, statusByte, senseLength, senseDataPtr);
  136.     RequestDone(requestPtr,status,byteCount);
  137.     return 0;
  138.  
  139. }
  140.  
  141. /*
  142.  *----------------------------------------------------------------------
  143.  *
  144.  * SendCmdToDevice --
  145.  *
  146.  *    Translate a Block Device request into and SCSI command and send it
  147.  *    to the disk device.
  148.  *
  149.  * Results:
  150.  *    SUCCESS is the command is sent otherwise a Sprite Error code.
  151.  *
  152.  * Side effects:
  153.  *    Disk may be read or written.
  154.  *
  155.  *----------------------------------------------------------------------
  156.  */
  157. static ReturnStatus
  158. SendCmdToDevice(diskPtr, requestPtr, firstSector, lengthInSectors)
  159.     ScsiDisk    *diskPtr;
  160.     DevBlockDeviceRequest *requestPtr;
  161.     unsigned int    firstSector;
  162.     unsigned int    lengthInSectors;
  163. {
  164.     int        cmd;
  165.     ScsiDiskCmd     *diskCmdPtr = (ScsiDiskCmd *) (requestPtr->ctrlData);
  166.  
  167.     cmd = (requestPtr->operation == FS_READ) ? SCSI_READ : SCSI_WRITE;
  168.     DevScsiGroup0Cmd(diskPtr->devPtr,cmd, firstSector, lengthInSectors,
  169.               &(diskCmdPtr->scsiCmd));
  170.     diskCmdPtr->scsiCmd.buffer = requestPtr->buffer;
  171.     diskCmdPtr->scsiCmd.bufferLen = lengthInSectors * SCSI_DISK_SECTOR_SIZE;
  172.     diskCmdPtr->scsiCmd.dataToDevice = (cmd == SCSI_WRITE);
  173.     diskCmdPtr->scsiCmd.doneProc = DiskDoneProc;
  174.     diskCmdPtr->scsiCmd.clientData = (ClientData) requestPtr;
  175.     diskCmdPtr->diskPtr = diskPtr;
  176.     (boot_SendSCSICommand)(diskPtr->devPtr,&(diskCmdPtr->scsiCmd));
  177.     return SUCCESS;
  178. }
  179.  
  180. /*
  181.  *----------------------------------------------------------------------
  182.  *
  183.  * DiskError --
  184.  *
  185.  *    Map SCSI errors indicated by the sense data into Sprite ReturnStatus
  186.  *    and error message. This proceedure handles two types of 
  187.  *    sense data Class 0 and class 7.
  188.  *
  189.  * Results:
  190.  *    A sprite error code.
  191.  *
  192.  * Side effects:
  193.  *    None.
  194.  *
  195.  *----------------------------------------------------------------------
  196.  */
  197. static ReturnStatus
  198. DiskError(diskPtr, statusByte, senseLength, senseDataPtr)
  199.     ScsiDisk     *diskPtr;    /* SCSI disk that's complaining. */
  200.     unsigned char statusByte;    /* The status byte of the command. */
  201.     int         senseLength;    /* Length of SCSI sense data in bytes. */
  202.     char     *senseDataPtr;    /* Sense data. */
  203. {
  204.     ReturnStatus status;
  205.     ScsiStatus *statusPtr = (ScsiStatus *) &statusByte;
  206.     ScsiClass0Sense *sensePtr = (ScsiClass0Sense *) senseDataPtr;
  207.     char    *name = diskPtr->devPtr->locationName;
  208.     char    errorString[MAX_SCSI_ERROR_STRING];
  209.  
  210.     /*
  211.      * Check for status byte to see if the command returned sense
  212.      * data. If no sense data exists then we only have the status
  213.      * byte to look at.
  214.      */
  215.     if (!statusPtr->check) {
  216.     if (SCSI_RESERVED_STATUS(statusByte) || statusPtr->intStatus) {
  217.         return SUCCESS;
  218.     } 
  219.     if (statusPtr->busy) {
  220.         return DEV_OFFLINE;
  221.     }
  222.     return SUCCESS;
  223.     }
  224.     if (senseLength == 0) {
  225.      return DEV_NO_SENSE;
  226.     }
  227.     if (DevScsiMapClass7Sense(senseLength, senseDataPtr,&status, errorString)) {
  228.     return status;
  229.     }
  230.  
  231.     /*
  232.      * If its not a class 7 error it must be Old style sense data..
  233.      */
  234.     if (sensePtr->error == SCSI_NO_SENSE_DATA) {        
  235.     status = SUCCESS;
  236.     } else {
  237.      status = DEV_HARD_ERROR;
  238.     }
  239.     return status;
  240. }
  241.  
  242. /*
  243.  *----------------------------------------------------------------------
  244.  *
  245.  * IOControlProc --
  246.  *
  247.  *      Do a special operation on a raw SCSI Disk.
  248.  *
  249.  * Results:
  250.  *      None.
  251.  *
  252.  * Side effects:
  253.  *      None.
  254.  *
  255.  *----------------------------------------------------------------------
  256.  */
  257.  
  258. /*ARGSUSED*/
  259. static ReturnStatus
  260. IOControlProc(handlePtr, command, inBufSize, inBuffer,
  261.                                  outBufSize, outBuffer)
  262.     DevBlockDeviceHandle    *handlePtr; /* Handle pointer of device. */
  263.     int command;
  264.     int inBufSize;
  265.     char *inBuffer;
  266.     int outBufSize;
  267.     char *outBuffer;
  268. {
  269. }
  270.  
  271. /*
  272.  *----------------------------------------------------------------------
  273.  *
  274.  * ReleaseProc --
  275.  *
  276.  *    Block device release proc.
  277.  *
  278.  * Results:
  279.  *    None.
  280.  *
  281.  * Side effects:
  282.  *    None.
  283.  *
  284.  *----------------------------------------------------------------------
  285.  */
  286. /*ARGUSED*/
  287. static ReturnStatus
  288. ReleaseProc(handlePtr)
  289.     DevBlockDeviceHandle    *handlePtr; /* Handle pointer of device. */
  290. {
  291. }
  292.  
  293. /*
  294.  *----------------------------------------------------------------------
  295.  *
  296.  * BlockIOProc --
  297.  *
  298.  *    Convert a Block device IO request in a SCSI command block and 
  299.  *    submit it to the HBA.
  300.  *
  301.  * Results:
  302.  *    The return code from the I/O operation.
  303.  *
  304.  * Side effects:
  305.  *    The disk write, if operation == FS_WRITE.
  306.  *
  307.  *----------------------------------------------------------------------
  308.  */
  309.  
  310. static ReturnStatus
  311. BlockIOProc(handlePtr, requestPtr) 
  312.     DevBlockDeviceHandle    *handlePtr; /* Handle pointer of device. */
  313.     DevBlockDeviceRequest *requestPtr; /* IO Request to be performed. */
  314. {
  315.     ReturnStatus status;    
  316.     ScsiDisk    *diskPtr = (ScsiDisk *) handlePtr;
  317.     unsigned int    firstSector, lengthInSectors, lastSector;
  318.  
  319.  
  320.     /*
  321.      * Insure that the request is within the bounds of the partition.
  322.      */
  323.     firstSector = requestPtr->startAddress/DEV_BYTES_PER_SECTOR;
  324.     lengthInSectors = requestPtr->bufferLen/DEV_BYTES_PER_SECTOR;
  325.  
  326.     status = SendCmdToDevice(diskPtr, requestPtr, firstSector, lengthInSectors);
  327.     return(status);
  328. }
  329.  
  330. /*
  331.  *----------------------------------------------------------------------
  332.  *
  333.  * DevScsiDiskAttach --
  334.  *
  335.  *    Attach a SCSI Disk device to the system.
  336.  *
  337.  * Results:
  338.  *    The DevBlockDeviceHandle of the device.
  339.  *
  340.  * Side effects:
  341.  *    None.
  342.  *
  343.  *----------------------------------------------------------------------
  344.  */
  345.  
  346. DevBlockDeviceHandle *
  347. DevScsiDiskAttach(devicePtr)
  348.     Fs_Device    *devicePtr;    /* The device to attach. */
  349. {
  350.     ScsiDevice    *devPtr;
  351.     ScsiDisk    *diskPtr;
  352.  
  353.     /*
  354.      * Ask the HBA to set up the path to the device. For the time being
  355.      * we will not sort the disk requests.
  356.      */
  357.     devPtr = DevScsiAttachDevice(devicePtr, DEV_QUEUE_FIFO_INSERT);
  358.     /*
  359.      * Initialize the ScsiDisk structure. We don't need to read the label
  360.      * if the user is opening the device in raw (non partitioned) mode.
  361.      */
  362.     diskPtr = InitDisk(devPtr,0);
  363.       diskPtr->partition =  0;
  364.  
  365.     diskPtr->blockHandle.blockIOProc = BlockIOProc;
  366.     diskPtr->blockHandle.releaseProc = ReleaseProc;
  367.     diskPtr->blockHandle.IOControlProc = IOControlProc;
  368.     diskPtr->blockHandle.minTransferUnit = SCSI_DISK_SECTOR_SIZE;
  369.     diskPtr->blockHandle.maxTransferSize = devPtr->maxTransferSize;
  370.     return (DevBlockDeviceHandle *) diskPtr;
  371. }
  372.  
  373.  
  374.